# coding: utf-8


def weight(u, neighbours, graph):
    count = 0
    sum_ = 0
    for v in neighbours:
        sum_ += graph.vs[v]["pos"]
        count += 1

    if count == 0:
        return graph.vs[u]["pos"]

    return sum_ / count


def gravity_heuristics(ordering, graph):  ### 顺序重心启发式
    sorted_ordering = []
    for layer in ordering:  ####他是一层一层来的，每进行完一层它的pos值都会更新
        sorted_layer = sorted(
            layer,
            key=lambda node: weight(node, graph.neighbors(node, mode="in"), graph),
        )
        for j, node in enumerate(sorted_layer):
            graph.vs[node]["pos"] = j
        sorted_ordering.append(sorted_layer)

    return sorted_ordering


def reverse_gravity_heuristic(ordering, graph):  ### 逆序重心启发式
    ed_ordering = []
    for layer in ordering[::-1]:
        sorted_layer = sorted(
            layer,
            key=lambda node: weight(node, graph.neighbors(node, mode="out"), graph),
        )
        for j, node in enumerate(sorted_layer):
            graph.vs[node]["pos"] = j
        ed_ordering.append(sorted_layer)
    ed_ordering = ed_ordering[::-1]
    return ed_ordering


def ing_number(u, v, graph):  # 每个小分层的交叉数
    count: int = 0
    for out_u in graph.neighbors(u, mode="out"):
        for out_v in graph.neighbors(v, mode="out"):
            if graph.vs[out_v]["pos"] < graph.vs[out_u]["pos"]:
                count += 1
    for in_u in graph.neighbors(u, mode="in"):
        for in_v in graph.neighbors(v, mode="in"):
            if graph.vs[in_v]["pos"] < graph.vs[in_u]["pos"]:
                count += 1

    return count


def greedy_switch_heuristic(ordering, graph):  # 两两交换节点
    improved: bool = True
    k: int = 0
    while improved:
        improved = False
        for layer in ordering:
            for i in range(len(layer) - 1):
                old = ing_number(layer[i], layer[i + 1], graph)
                graph.vs[layer[i]]["pos"], graph.vs[layer[i + 1]]["pos"] = (
                    graph.vs[layer[i + 1]]["pos"],
                    graph.vs[layer[i]]["pos"],
                )
                # print('old', old)
                next = ing_number(layer[i + 1], layer[i], graph)
                # print('next', next)
                # diff = old - next
                if old > next:
                    improved = True
                    layer[i], layer[i + 1] = layer[i + 1], layer[i]
                else:
                    graph.vs[layer[i]]["pos"], graph.vs[layer[i + 1]]["pos"] = (
                        graph.vs[layer[i + 1]]["pos"],
                        graph.vs[layer[i]]["pos"],
                    )

        k += 1
